package com.summer.safe.quartz.utils;

import com.summer.safe.exception.CustomException;
import com.summer.safe.quartz.config.QuartzJobFactory;
import com.summer.safe.quartz.config.QuartzJobFactoryDisallowConcurrentExecution;
import com.summer.safe.quartz.entity.QuartzJob;
import org.quartz.*;


/**
 * 定时任务的执行类
 */
public class QuartzUtils {



    /**
     * 需要执行的任务类
     *
     * @param quartzJob 执行计划
     * @return 具体执行任务类(并发or禁止并发)
     */
    private static Class<? extends Job> getJobClass(QuartzJob quartzJob) {

        Class<? extends Job> clazz = QuartzJob.CONCURRENT_IS.equals(quartzJob.getConcurrent()) ? QuartzJobFactory.class : QuartzJobFactoryDisallowConcurrentExecution.class;
        return clazz;
    }


    /**
     * 添加任务
     *
     * @param quartzJob
     * @throws SchedulerException
     */
    public static void addJob(QuartzJob quartzJob,Scheduler scheduler) throws SchedulerException {
            //r任务的id
            String jobId=quartzJob.getId();
            //任务的工作组
            String jobGroup=quartzJob.getJobGroup();
            //触发器
            TriggerKey triggerKey =getTriggerKey(jobId,jobGroup);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            // 不存在，创建一个
            if (null == trigger) {
                Class<? extends Job> jobClass = getJobClass(quartzJob);
                JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId,jobGroup)).build();
                //存入参数
                jobDetail.getJobDataMap().put(QuartzJob.TASK_TARGET, quartzJob);
                //Cron表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
                //触发器对象
                trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId,jobGroup)).withSchedule(scheduleBuilder).build();

                // 判断是否存在
                if (scheduler.checkExists(getJobKey(jobId, jobGroup))) {
                    // 防止创建时存在数据问题 先移除，然后在执行创建操作
                    scheduler.deleteJob(getJobKey(jobId, jobGroup));
                }
                //开启任务
                scheduler.scheduleJob(jobDetail, trigger);
            } else {
                // Trigger已存在，那么更新相应的定时设置
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
                // 按新的cronExpression表达式重新构建trigger
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
                // 按新的trigger重新设置job执行
                scheduler.rescheduleJob(triggerKey, trigger);
            }
        }





    /**
     * 立即执行job
     *
     * @throws SchedulerException
     */
    public static void runAJobNow(QuartzJob quartzJob, Scheduler scheduler) throws SchedulerException {
        addJob(quartzJob,scheduler);
        // 参数
        JobDataMap jobDetail = new JobDataMap();
        jobDetail.put(QuartzJob.TASK_TARGET, quartzJob);
        scheduler.triggerJob(getJobKey(quartzJob.getId(), quartzJob.getJobGroup()), jobDetail);
    }

    /**
     * 暂停一个job
     *
     * @param quartzJob
     * @throws SchedulerException
     */
    public static void pauseJob(QuartzJob quartzJob,Scheduler scheduler) throws SchedulerException {
        scheduler.pauseJob(getJobKey(quartzJob.getId(),quartzJob.getJobGroup()));
    }

    /**
     * 恢复一个job
     *
     * @param quartzJob
     * @throws SchedulerException
     */
    public static void resumeJob(QuartzJob quartzJob,Scheduler scheduler) throws SchedulerException {

        scheduler.resumeJob(getJobKey(quartzJob.getId(),quartzJob.getJobGroup()));
    }


    /**
     * 删除一个job
     *
     * @param quartzJob
     * @throws SchedulerException
     */
    public static void deleteJob(QuartzJob quartzJob,Scheduler scheduler) throws SchedulerException {
        scheduler.deleteJob(getJobKey(quartzJob.getId(),quartzJob.getJobGroup()));
    }




    /**
     * 更新job时间表达式
     *
     * @param quartzJob
     * @throws SchedulerException
     */
    public static void updateJobCron(QuartzJob quartzJob,Scheduler scheduler) throws SchedulerException {
        // 判断是否存在
        JobKey jobKey = getJobKey(quartzJob.getId(), quartzJob.getJobGroup());
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        addJob(quartzJob,scheduler);
    }


    /**
     * 更改任务状态
     *
     * @param quartzJob
     * @return
     */
    public static void updateJobStatus(QuartzJob quartzJob,Scheduler scheduler) {
        try {
            //停止后的启动
            if (quartzJob.STATUS_RUNNING.equals(quartzJob.getStatus())) {
                runAJobNow(quartzJob,scheduler);
            }
            //暂停
            else if (quartzJob.STATUS_NOT_RUNNING.equals(quartzJob.getStatus())) {
                pauseJob(quartzJob,scheduler);
            }
            //暂停后的恢复
            else if (quartzJob.STATUS_RECOVERY_RUNNING.equals(quartzJob.getStatus())) {
                resumeJob(quartzJob,scheduler);
            }
            //停止
            else if (quartzJob.STATUS_STOP_RUNNING.equals(quartzJob.getStatus())) {
                deleteJob(quartzJob,scheduler);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }


    /**
     * 创建任务触发对象
     *
     */
    public static TriggerKey getTriggerKey(String jobId, String jobGroup) {
        return TriggerKey.triggerKey(QuartzJob.TASK__NAME + jobId, jobGroup);
    }
    /**
     * 创建任务键对象
     */
    public static JobKey getJobKey(String jobId, String jobGroup){
        return JobKey.jobKey(QuartzJob.TASK__NAME + jobId, jobGroup);
    }
}


